package demo.spring.framework.beans.factory;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.beans.factory.support.FactoryBeanRegistrySupport;
import org.springframework.core.AliasRegistry;
import org.springframework.core.SimpleAliasRegistry;

/**
 * Spring Bean的创建是典型的工厂模式，这一系列的Bean工厂，也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务。
 * <p>
 * BeanFactory作为最顶层的一个接口类，它定义了IOC容器的基本功能规范，BeanFactory
 * 有三个子类：ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。 最终的默认实现类是
 * DefaultListableBeanFactory，他实现了所有的接口。
 *
 * Bean Factory的实现应该尽可能的实现标准的Bean生命周期接口，完整的初始化方法标准顺序如下:
 * <ol>
 * <li>org.springframework.beans.factory.BeanNameAware's {@code setBeanName}
 * <li>org.springframework.beans.factory.BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>org.springframework.beans.factory.BeanFactoryAware's {@code setBeanFactory}
 * <li>org.springframework.context.EnvironmentAware's {@code setEnvironment}
 * <li>org.springframework.context.EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>org.springframework.context.ResourceLoaderAware's {@code setResourceLoader} (only applicable
 * when running in an application context)
 * <li>org.springframework.context.ApplicationEventPublisherAware's
 * {@code setApplicationEventPublisher}(only applicable when running in an application context)
 * <li>org.springframework.context.MessageSourceAware's {@code setMessageSource} (only applicable
 * when running in an application context)
 * <li>org.springframework.context.ApplicationContextAware's {@code setApplicationContext} (only
 * applicable when running in an application context)
 * <li>org.springframework.web.context.ServletContextAware's {@code setServletContext} (only
 * applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of
 * org.springframework.beans.factory.config.BeanPostProcessor
 * <li>org.springframework.beans.factory.InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of
 * org.springframework.beans.factory.config.BeanPostProcessor
 * </ol>
 * 
 * 关闭Bean Factory时，执行下面的方法：
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>org.springframework.beans.factory.DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>
 */
public class BeanFactoryDemo {

    public void beanPostProcessor() {
        BeanPostProcessor BeanPostProcessor = null;
    }

    /**
     * SimpleAliasRegistry中定义了一个Map用于保存别名与正式名字的映射
     */
    public void aliasRegistry() {
        AliasRegistry aliasRegistry = new SimpleAliasRegistry();

    }

    /**
     * DefaultSingletonBeanRegistry继承了SimpleAliasRegistry并实现SingletonBeanRegistry，使得它既有管理
     * SingletonBean的功能，又提供了别名的功能，它是一个通用的存储共享bean实例的地方。在注册一个SingletonBean的时候，用到了四个存储器：
     * 
     * <li>singletonObjects：用来存放注册的SingletonBean，具体的实现类是ConcurrentHashMap。
     * <li>singletonFactories：存储制造singleton的工厂，当Spring制造一个bean时因为依赖的bean还未完成
     * Spring的单例制造会将前者包装成一个ObjectFactory放入。 ObjectFactory的返回值就是bean。
     * <li>earlySingletonObjects：是singletonFactory 制造出来的 singleton 的缓存。
     * <li>registeredSingletons：按顺序存放已经注册的SingletonBean的名称。singletonObjects：用来存放注册的SingletonBean，具体的实现类是ConcurrentHashMap。
     */
    public void defaultSingletonBeanRegistry() {
        DefaultSingletonBeanRegistry singletonBeanRegistry = new DefaultSingletonBeanRegistry();
        /**
         * getSingleton的时候，spring的默认实现是，先从singletonObjects寻找，如果找不到，再从earlySingletonObjects寻找，仍然找不到，那就从
         * singletonFactories寻找对应的制造singleton的工厂，然后调用工厂的getObject方法，造出对应的SingletonBean，并放入earlySingletonObjects中。
         */
        Object bean = singletonBeanRegistry.getSingleton("beanName");

    }

    /**
     * FactoryBeanRegistrySupport增加了对FactoryBean的支持，getObjectFromFactoryBean()方法首先判断该FatoryBean是否为单利，不是则没都调用
     * factory bean的getObject()方法创建新的bean，否则只创建一次放入缓存中，以后从缓存中取出的单利实现方式。
     */
    public void factoryBeanRegistrySupport() {
        FactoryBeanRegistrySupport factoryBeanRegistrySupport = new DefaultListableBeanFactory();
    }

    /**
     * BeanFactory最核心的方法应该就是getBean()了，有多个重载方法最终都是通过调用doGetBean()方法完成对bean的获取，根据 bean
     * name从缓存容器中查找如果找不到，则会先创建bean在放入容器中。
     */
    public void beanFactory() {
        BeanFactory beanFactory = new DefaultListableBeanFactory();
        Object bean = beanFactory.getBean("beanName");
    }

    /**
     * ListableBeanFactory 接口表示这些 Bean 是可列表的
     */
    @Test
    public void listableBeanFactory() {
        ListableBeanFactory listableBeanFactory = new DefaultListableBeanFactory();
    }

    /**
     * HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的，也就是每个Bean 有可能有父 Bean
     */
    @Test
    public void hierarchicalBeanFactory() {
        HierarchicalBeanFactory listableBeanFactory = new DefaultListableBeanFactory();
    }

    /**
     * AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则
     */
    @Test
    public void autowireCapableBeanFactory() {
        AutowireCapableBeanFactory listableBeanFactory = new DefaultListableBeanFactory();
    }

}
